package hos.thread

import android.annotation.SuppressLint
import android.os.Looper
import android.util.Log
import java.util.concurrent.BlockingQueue
import java.util.concurrent.LinkedBlockingQueue
import java.util.concurrent.ThreadFactory
import java.util.concurrent.ThreadPoolExecutor
import java.util.concurrent.TimeUnit
import java.util.concurrent.atomic.AtomicInteger
import kotlin.math.max
import kotlin.math.min

/**
 * <p>Title: ThreadExecutor </p>
 * <p>Description:  </p>
 * <p>Company: www.mapuni.com </p>
 *
 * @author : 蔡俊峰
 * @date : 2024-08-06 9:40
 * @version : 1.0
 */
class ThreadPool @JvmOverloads constructor(
    keepAliveTime: Long = 30L,
    cpuCount: Int = Runtime.getRuntime().availableProcessors(),
    workQueue: BlockingQueue<Runnable> = LinkedBlockingQueue<Runnable>(),
) : ThreadPoolExecutor(
    max(4, min(cpuCount + 1, 5)),
    cpuCount * 2 + 1,
    keepAliveTime, TimeUnit.SECONDS,
    workQueue,
    object : ThreadFactory {
        private val threadId by lazy { AtomicInteger(0) }

        @SuppressLint("DefaultLocale")
        override fun newThread(r: Runnable?): Thread {
            return Thread(r, String.format("hos_io_%d", threadId.getAndIncrement()))
        }
    }
) {

    init {
        //允许核心线程回收
        allowCoreThreadTimeOut(true)
    }

    override fun afterExecute(r: Runnable?, t: Throwable?) {
        super.afterExecute(r, t)
        Log.d("Thread: ", "activeCount:$activeCount")
        Log.d("Thread: ", "ThreadName" + Thread.currentThread().name)
    }

    fun postIo(
        block: () -> Unit
    ) {
        execute {
            block()
        }
    }

    fun postOnIo(block: () -> Unit) {
        if (isMainThread()) {
            // 在主线程
            execute {
                block()
            }
            return
        }
        block()
    }

    companion object {

        @JvmStatic
        val thread by lazy {
            get()
        }

        @JvmStatic
        @Synchronized
        private fun get() = ThreadPool()

        @JvmStatic
        fun isMainThread(): Boolean {
            return Looper.getMainLooper().thread === Thread.currentThread()
        }
    }
}